"""
版本说明：相对02版，增加了开平仓交易记录功能，所有交易记录将存入 trade_records 表
"""
import time, os, sqlite3
from threading import Thread, Lock as threading_Lock
import numpy as np
import pandas as pd
from tqsdk import TqApi, TqAuth, TqKq
from rich.console import Console
from rich.theme import Theme
from MyTT import REF, EMA, SUM
import logging

# 配置日志记录
logging.basicConfig(
    filename='trading_log.log',
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s'
)

# 改变控制台背景色和字体色，控制台窗口大小
os.system("COLOR 02")
os.system("mode con cols=150 lines=50")

# 定义颜色主题
# 定义更明亮显眼的颜色主题
custom_theme = Theme({
    "info": "bright_cyan",
    "warning": "bright_yellow",
    "error": "bright_red",
    "success": "bright_green",
    "trade": "bold bright_magenta"
})
console = Console(theme=custom_theme)

# 定义全局变量
symbols = []
api = None
threads = []
opened_positions = set()  # 记录已开仓的品种
position_lock = threading_Lock()  # 添加锁以保护opened_positions的并发访问


# 检查是否有未完成订单和实际持仓
def check_position_and_orders(api, symbol):
    """
    检查指定品种是否有未完成订单或已有持仓
    :param api: TqSdk API对象
    :param symbol: 交易品种
    :return: (bool, str) - (是否可以开仓, 原因)
    """
    try:
        # 检查持仓情况
        position = api.get_position(symbol)
        if position.pos_long > 0:
            return False, f"{symbol}已有{position.pos_long}手多仓持仓"
        if position.pos_short > 0:
            return False, f"{symbol}已有{position.pos_short}手空仓持仓"
        
        # 检查未完成订单
        orders = api.get_order()
        if hasattr(orders, 'list') and callable(orders.list):
            order_list = orders.list()
        elif isinstance(orders, list):
            order_list = orders
        else:
            order_list = list(orders)
        
        for order in order_list:
            if hasattr(order, 'get'):
                order_symbol = order.get('symbol')
                order_status = order.get('status')
            else:
                order_symbol = order['symbol']
                order_status = order['status']
            
            if order_symbol == symbol and order_status != 'FINISHED' and order_status != 'CANCELED':
                return False, f"{symbol}有未完成订单"
        
        return True, "可以开仓"
    except Exception as e:
        logging.error(f"检查{symbol}持仓和订单时出错: {str(e)}", exc_info=True)
        return False, f"检查出错: {str(e)}"


# 新增函数：获取 config 表所有配置项
def get_all_configs():
    """
    从 config 表中获取所有配置项，以字典形式返回
    :return: 包含所有配置项的字典
    """
    try:
        conn = sqlite3.connect('trade_monitor.db')
        cursor = conn.cursor()
        cursor.execute("SELECT key, value FROM config")
        results = cursor.fetchall()
        conn.close()
        return dict(results)
    except Exception as e:
        console.print(f"从数据库获取所有配置项时出错: {e}", style="error")
        return {}

def get_symbols():
    try:
        conn = sqlite3.connect('trade_monitor.db')
        cursor = conn.cursor()
        # 查询品种代码和 mtp 字段
        cursor.execute("SELECT exchange_code FROM products WHERE is_monitored=1")
        products = cursor.fetchall()
        conn.close()
        # 返回包含品种代码和 mtp 值的列表
        return [product[0] for product in products]
    except Exception as e:
        console.print(f"从数据库获取监控品种时出错: {e}", style="error")
        return []

# 新增函数：记录交易到数据库
def insert_trade_record(trade_time, symbol, direction, action_type, volume, price, remark):
    try:
        # 如果没有传入时间戳，则获取当前时间戳
        if not trade_time:
            trade_time = time.strftime('%Y-%m-%d %H:%M:%S')
        
        logging.info(f"准备插入交易记录: symbol={symbol}, direction={direction}, action_type={action_type}, volume={volume}, price={price}, remark={remark}")
        conn = sqlite3.connect('trade_monitor.db')
        cursor = conn.cursor()
        
        # 确保价格是数值类型
        try:
            price = float(price)
        except (ValueError, TypeError):
            price = 0.0
            console.print(f"价格格式无效，设置为0: {symbol}", style="warning")
        
        logging.info(f"尝试插入数据: trade_time={trade_time}, symbol={symbol}, direction={direction}, action_type={action_type}, volume={volume}, price={price}, remark={remark}")
        cursor.execute(
            "INSERT INTO trade_records (trade_time, symbol, direction, action_type, volume, price, remark) "
            "VALUES (?, ?, ?, ?, ?, ?, ?)",
            (trade_time, symbol, direction, action_type, volume, price, remark)
        )
        conn.commit()
        conn.close()
        
        # 记录成功日志
        logging.info(f"交易记录已成功插入数据库: {symbol} {direction} {volume}手 @ {price}")
    except sqlite3.OperationalError as e:
        console.print(f"数据库操作错误: {e}", style="error")
        logging.error(f"数据库操作错误: {e}")
    except sqlite3.IntegrityError as e:
        console.print(f"数据库完整性错误: {e}", style="error")
        logging.error(f"数据库完整性错误: {e}")
    except Exception as e:
        console.print(f"记录交易到数据库时出错: {e}", style="error")
        logging.error(f"记录交易到数据库时出错: {e}")

def stop_loss(symbol):
    try:
        conn = sqlite3.connect('trade_monitor.db')
        cursor = conn.cursor()

        cursor.execute("SELECT limit_stoploss,mtp,dks FROM products WHERE exchange_code=? AND is_monitored=1", (symbol,))
        result = cursor.fetchone()
        conn.close()
        if result is None:
            stop_loss_limit = 3000  # 限额止损
            mtp = 5  # 移动止盈止损周期
            dks = "双向"  # 开仓方向
        else:
            stop_loss_limit = int(result[0])  # 限额止损
            # 处理 mtp 数据，确保其为有效的整数
            try:
                mtp = int(result[1])
                # 限制 mtp 在合理范围内，例如 1 到 3600
                mtp = max(1, min(mtp, 3600))
            except (ValueError, TypeError):
                console.print(f"从数据库获取 {symbol} 的 mtp 值无效，使用默认值", style="warning")
                mtp = 5
            dks = str(result[2])  # 开仓方向
    except Exception as e:
        console.print(f"从数据库获取 {symbol} 止损限额时出错: {e}", style="error")
        return
    console.print(f"{time.strftime('%X')} 开始检查{symbol}止损条件", style="warning")
    klines = api.get_kline_serial(symbol, 60 * mtp, data_length=300)
    quote = api.get_quote(symbol)
    position = api.get_position(symbol)
    orders = api.get_order(symbol)

    console.print(f"{time.strftime('%X')} 开始处理 {symbol}", style="warning")
    if True:
        console.print(f"{time.strftime('%X')} 数据更新", style="info")
        try:
            # 撤销所有未成交订单
            for order in orders.items():
                if hasattr(order, 'status') and order.status == 'ALIVE':
                    api.cancel_order(order)

            # ***************************************限额止损检查***************************************
            if position.pos_short > 0:
                short_loss_per_hand = (position.open_price_short - quote.last_price) * quote.volume_multiple 
                if short_loss_per_hand > stop_loss_limit:
                    if symbol.startswith('SHFE'):
                        if position.pos_short_today > 0:
                            limit_price = quote.ask_price1 + 2 * quote.price_tick
                            volume = position.pos_short_today
                            if volume > 0:
                                # 平仓并获取订单ID
                                order_id = api.insert_order(
                                    symbol=symbol,
                                    direction="BUY",
                                    offset="CLOSETODAY",
                                    volume=volume,
                                    limit_price=limit_price
                                )
                                console.print(
                                    f"{time.strftime('%X')} 平SHFE{symbol}今空仓(限额止损): 手数: {volume}, 订单ID: {order_id}",
                                    style="trade"
                                )
                                # 仅保留下单信息日志
                                logging.info(
                                    f"平SHFE{symbol}今空仓(限额止损): 手数: {volume}, 平仓价格: {limit_price}, 订单ID: {order_id}"
                                )

                                # 检查订单是否在0.3秒内成交
                                deadline = time.time() + 0.3
                                order_filled = False
                                while time.time() < deadline:
                                    api.wait_update(deadline=deadline)
                                    order = api.get_order(order_id)
                                    if order and order['status'] == 'FINISHED':
                                        order_filled = True
                                        console.print(
                                            f"{time.strftime('%X')} SHFE{symbol}今空仓平仓订单已成交",
                                            style="success"
                                        )
                                        logging.info(f"SHFE{symbol}今空仓平仓订单已成交: {order_id}")
                                        insert_trade_record(trade_time, symbol, "BUY", "CLOSETODAY", volume, limit_price, "限额止损")
                                        break

                                # 如果未成交，撤销订单
                                if not order_filled:
                                    api.cancel_order(order_id)
                                    console.print(
                                        f"{time.strftime('%X')} SHFE{symbol}今空仓平仓订单0.3秒未成交，已撤销",
                                        style="warning"
                                    )
                                    logging.info(f"SHFE{symbol}今空仓平仓订单0.3秒未成交，已撤销: {order_id}")
                        if position.pos_short_his > 0:
                            limit_price = quote.ask_price1 + 2 * quote.price_tick
                            volume = position.pos_short_his
                            if volume > 0:
                                # 平仓并获取订单ID
                                order_id = api.insert_order(
                                    symbol=symbol,
                                    direction="CLOSE",
                                    volume=volume,
                                    limit_price=limit_price
                                )
                                console.print(
                                    f"{time.strftime('%X')} 平SHFE{symbol}昨空仓(限额止损): 手数: {volume}, 订单ID: {order_id}",
                                    style="trade"
                                )
                                # 仅保留下单信息日志
                                logging.info(
                                    f"平SHFE{symbol}昨空仓(限额止损): 手数: {volume}, 平仓价格: {limit_price}, 订单ID: {order_id}"
                                )

                                # 检查订单是否在0.3秒内成交
                                deadline = time.time() + 0.3
                                order_filled = False
                                while time.time() < deadline:
                                    api.wait_update(deadline=deadline)
                                    order = api.get_order(order_id)
                                    if order and order['status'] == 'FINISHED':
                                        order_filled = True
                                        console.print(
                                            f"{time.strftime('%X')} SHFE{symbol}昨空仓平仓订单已成交",
                                            style="success"
                                        )
                                        logging.info(f"SHFE{symbol}昨空仓平仓订单已成交: {order_id}")
                                        insert_trade_record(trade_time, symbol, "BUY", "CLOSE", volume, limit_price, "限额止损")
                                        break

                                # 如果未成交，撤销订单
                                if not order_filled:
                                    api.cancel_order(order_id)
                                    console.print(
                                        f"{time.strftime('%X')} SHFE{symbol}昨空仓平仓订单0.3秒未成交，已撤销",
                                        style="warning"
                                    )
                                    logging.info(f"SHFE{symbol}昨空仓平仓订单0.3秒未成交，已撤销: {order_id}")
                    else:
                        if position.pos_short > 0:
                            limit_price = quote.ask_price1 + 2 * quote.price_tick
                            volume = position.pos_short
                            if volume > 0:
                                # 平仓并获取订单ID
                                order_id = api.insert_order(
                                    symbol=symbol,
                                    direction="CLOSE",
                                    volume=volume,
                                    limit_price=limit_price
                                )
                                console.print(
                                    f"{time.strftime('%X')} 平{symbol}空仓(限额止损): 手数: {volume}, 订单ID: {order_id}",
                                    style="trade"
                                )
                                # 仅保留下单信息日志
                                logging.info(
                                    f"平{symbol}空仓(限额止损): 手数: {volume}, 平仓价格: {limit_price}, 订单ID: {order_id}"
                                )

                                # 检查订单是否在0.3秒内成交
                                deadline = time.time() + 0.3
                                order_filled = False
                                while time.time() < deadline:
                                    api.wait_update(deadline=deadline)
                                    order = api.get_order(order_id)
                                    if order and order['status'] == 'FINISHED':
                                        order_filled = True
                                        console.print(
                                            f"{time.strftime('%X')} {symbol}空仓平仓订单已成交",
                                            style="success"
                                        )
                                        logging.info(f"{symbol}空仓平仓订单已成交: {order_id}")
                                        insert_trade_record(trade_time, symbol, "BUY", "CLOSE", volume, limit_price, "限额止损")
                                        break

                                # 如果未成交，撤销订单
                                if not order_filled:
                                    api.cancel_order(order_id)
                                    console.print(
                                        f"{time.strftime('%X')} {symbol}空仓平仓订单0.3秒未成交，已撤销",
                                        style="warning"
                                    )
                                    logging.info(f"{symbol}空仓平仓订单0.3秒未成交，已撤销: {order_id}")


            if position.pos_long > 0:
                long_loss_per_hand = (quote.last_price - position.open_price_long) * quote.volume_multiple 
                if long_loss_per_hand > stop_loss_limit:
                    if symbol.startswith('SHFE'):
                        if position.pos_long_today > 0:
                            limit_price = quote.bid_price1 - 2 * quote.price_tick
                            volume = position.pos_long_today
                            if volume > 0:
                                # 平仓并获取订单ID
                                order_id = api.insert_order(
                                    symbol=symbol,
                                    direction="SELL",
                                    offset="CLOSETODAY",
                                    volume=volume,
                                    limit_price=limit_price
                                )
                                console.print(
                                    f"{time.strftime('%X')} 平SHFE{symbol}今多仓(限额止损): 手数: {volume}, 订单ID: {order_id}",
                                    style="trade"
                                )
                                # 仅保留下单信息日志
                                logging.info(
                                    f"平SHFE{symbol}今多仓(限额止损): 手数: {volume}, 平仓价格: {limit_price}, 订单ID: {order_id}"
                                )

                                # 检查订单是否在0.3秒内成交
                                deadline = time.time() + 0.3
                                order_filled = False
                                while time.time() < deadline:
                                    api.wait_update(deadline=deadline)
                                    order = api.get_order(order_id)
                                    if order and order['status'] == 'FINISHED':
                                        order_filled = True
                                        console.print(
                                            f"{time.strftime('%X')} SHFE{symbol}今多仓平仓订单已成交",
                                            style="success"
                                        )
                                        logging.info(f"SHFE{symbol}今多仓平仓订单已成交: {order_id}")
                                        insert_trade_record(trade_time, symbol, "SELL", "CLOSETODAY", volume, limit_price, "限额止损")
                                        break

                                # 如果未成交，撤销订单
                                if not order_filled:
                                    api.cancel_order(order_id)
                                    console.print(
                                        f"{time.strftime('%X')} SHFE{symbol}今多仓平仓订单0.3秒未成交，已撤销",
                                        style="warning"
                                    )
                                    logging.info(f"SHFE{symbol}今多仓平仓订单0.3秒未成交，已撤销: {order_id}")
                        if position.pos_long_his > 0:
                            limit_price = quote.bid_price1 - 2 * quote.price_tick
                            volume = position.pos_long_his
                            if volume > 0:
                                # 平仓并获取订单ID
                                order_id = api.insert_order(
                                    symbol=symbol,
                                    direction="SELL",
                                    offset="CLOSE",
                                    volume=volume,
                                    limit_price=limit_price
                                )
                                console.print(
                                    f"{time.strftime('%X')} 平SHFE{symbol}昨多仓(限额止损): 手数: {volume}, 订单ID: {order_id}",
                                    style="trade"
                                )
                                # 仅保留下单信息日志
                                logging.info(
                                    f"平SHFE{symbol}昨多仓(限额止损): 手数: {volume}, 平仓价格: {limit_price}, 订单ID: {order_id}"
                                )

                                # 检查订单是否在0.3秒内成交
                                deadline = time.time() + 0.3
                                order_filled = False
                                while time.time() < deadline:
                                    api.wait_update(deadline=deadline)
                                    order = api.get_order(order_id)
                                    if order and order['status'] == 'FINISHED':
                                        order_filled = True
                                        console.print(
                                            f"{time.strftime('%X')} SHFE{symbol}昨多仓平仓订单已成交",
                                            style="success"
                                        )
                                        logging.info(f"SHFE{symbol}昨多仓平仓订单已成交: {order_id}")
                                        insert_trade_record(trade_time, symbol, "SELL", "CLOSE", volume, limit_price, "限额止损")
                                        break

                                # 如果未成交，撤销订单
                                if not order_filled:
                                    api.cancel_order(order_id)
                                    console.print(
                                        f"{time.strftime('%X')} SHFE{symbol}昨多仓平仓订单0.3秒未成交，已撤销",
                                        style="warning"
                                    )
                                    logging.info(f"SHFE{symbol}昨多仓平仓订单0.3秒未成交，已撤销: {order_id}")
                    else:
                        if position.pos_long > 0:
                            limit_price = quote.bid_price1 - 2 * quote.price_tick
                            volume = position.pos_long
                            if volume > 0:
                                # 平仓并获取订单ID
                                order_id = api.insert_order(
                                    symbol=symbol,
                                    direction="SELL",
                                    offset="CLOSE",
                                    volume=volume,
                                    limit_price=limit_price
                                )
                                console.print(
                                    f"{time.strftime('%X')} 平{symbol}多仓(限额止损): 手数: {volume}, 订单ID: {order_id}",
                                    style="trade"
                                )
                                # 仅保留下单信息日志
                                logging.info(
                                    f"平{symbol}多仓(限额止损): 手数: {volume}, 平仓价格: {limit_price}, 订单ID: {order_id}"
                                )

                                # 检查订单是否在0.3秒内成交
                                deadline = time.time() + 0.3
                                order_filled = False
                                while time.time() < deadline:
                                    api.wait_update(deadline=deadline)
                                    order = api.get_order(order_id)
                                    if order and order['status'] == 'FINISHED':
                                        order_filled = True
                                        console.print(
                                            f"{time.strftime('%X')} {symbol}多仓平仓订单已成交",
                                            style="success"
                                        )
                                        logging.info(f"{symbol}多仓平仓订单已成交: {order_id}")
                                        insert_trade_record(trade_time, symbol, "SELL", "CLOSE", volume, limit_price, "限额止损")
                                        break

                                # 如果未成交，撤销订单
                                if not order_filled:
                                    api.cancel_order(order_id)
                                    console.print(
                                        f"{time.strftime('%X')} {symbol}多仓平仓订单0.3秒未成交，已撤销",
                                        style="warning"
                                    )
                                    logging.info(f"{symbol}多仓平仓订单0.3秒未成交，已撤销: {order_id}")

            # ***************************************趋势追踪止损检查***************************************
            close = klines.close
            low = klines.low
            open = klines.open
            high = klines.high
            close = np.array(close)
            low = np.array(low)
            open = np.array(open)
            high = np.array(high)

            Q = (3 * close + low + open + high) / 6
            terms = [
                26 * Q,
                25 * REF(Q, 1),
                24 * REF(Q, 2),
                23 * REF(Q, 3),
                22 * REF(Q, 4),
                21 * REF(Q, 5),
                20 * REF(Q, 6),
                19 * REF(Q, 7),
                18 * REF(Q, 8),
                17 * REF(Q, 9),
                16 * REF(Q, 10),
                15 * REF(Q, 11),
                14 * REF(Q, 12),
                13 * REF(Q, 13),
                12 * REF(Q, 14),
                11 * REF(Q, 15),
                10 * REF(Q, 16),
                9 * REF(Q, 17),
                8 * REF(Q, 18),
                7 * REF(Q, 19),
                6 * REF(Q, 20),
                5 * REF(Q, 21),
                4 * REF(Q, 22),
                3 * REF(Q, 23),
                2 * REF(Q, 24),
                REF(Q, 25)
            ]
            trading_line = sum(terms) / 351
            short_line = EMA(trading_line, 7)
            #logging.info(f"Symbol: {symbol}, Trading Line[-2]: {trading_line[-2]}, Short Line[-2]: {short_line[-2]}")
            console.print(f"条件值是： {trading_line[-2]}, {short_line[-2]}",style="trade")

            if len(trading_line) >= 2 and len(short_line) >= 2:
                # 处理空单
                if  trading_line[-2] > short_line[-2]:
                    if symbol.startswith('SHFE'):
                        if position.pos_short_today > 0:
                            limit_price = quote.ask_price1 + 2 * quote.price_tick
                            # 平仓并获取订单ID
                            order_id = api.insert_order(
                                symbol=symbol,
                                direction="BUY",
                                offset="CLOSETODAY",
                                volume=position.pos_short_today,
                                limit_price=limit_price
                            )
                            console.print(
                                f"{time.strftime('%X')} 平SHFE{symbol}今空仓(均线追踪止损): 手数: {position.pos_short_today}, 订单ID: {order_id}",
                                style="trade"
                            )
                            logging.info(
                                f"平SHFE{symbol}今空仓(均线追踪止损): 手数: {position.pos_short_today}, 平仓价格: {limit_price}, 订单ID: {order_id}"
                            )

                            # 检查订单是否在0.3秒内成交
                            deadline = time.time() + 0.3
                            order_filled = False
                            while time.time() < deadline:
                                api.wait_update(deadline=deadline)
                                order = api.get_order(order_id)
                                if order and order['status'] == 'FINISHED':
                                    order_filled = True
                                    console.print(
                                        f"{time.strftime('%X')} SHFE{symbol}今空仓平仓订单已成交",
                                        style="success"
                                    )
                                    logging.info(f"SHFE{symbol}今空仓平仓订单已成交: {order_id}")
                                    insert_trade_record(trade_time, symbol, "BUY", "CLOSETODAY", position.pos_short_today, limit_price, "均线追踪止损")
                                    break

                            # 如果未成交，撤销订单
                            if not order_filled:
                                api.cancel_order(order_id)
                                console.print(
                                    f"{time.strftime('%X')} SHFE{symbol}今空仓平仓订单0.3秒未成交，已撤销",
                                    style="warning"
                                )
                                logging.info(f"SHFE{symbol}今空仓平仓订单0.3秒未成交，已撤销: {order_id}")
                        if position.pos_short_his > 0:
                            limit_price = quote.ask_price1 + 2 * quote.price_tick
                            # 平仓并获取订单ID
                            order_id = api.insert_order(
                                symbol=symbol,
                                direction="BUY",
                                offset="CLOSE",
                                volume=position.pos_short_his,
                                limit_price=limit_price
                            )
                            console.print(
                                f"{time.strftime('%X')} 平SHFE{symbol}昨空仓(均线追踪止损): 手数: {position.pos_short_his}, 订单ID: {order_id}",
                                style="trade"
                            )
                            logging.info(
                                f"平SHFE{symbol}昨空仓(均线追踪止损): 手数: {position.pos_short_his}, 平仓价格: {limit_price}, 订单ID: {order_id}"
                            )

                            # 检查订单是否在0.3秒内成交
                            deadline = time.time() + 0.3
                            order_filled = False
                            while time.time() < deadline:
                                api.wait_update(deadline=deadline)
                                order = api.get_order(order_id)
                                if order and order['status'] == 'FINISHED':
                                    order_filled = True
                                    console.print(
                                        f"{time.strftime('%X')} SHFE{symbol}昨空仓平仓订单已成交",
                                        style="success"
                                    )
                                    logging.info(f"SHFE{symbol}昨空仓平仓订单已成交: {order_id}")
                                    insert_trade_record(trade_time, symbol, "BUY", "CLOSE", position.pos_short_his, limit_price, "均线追踪止损")
                                    break

                            # 如果未成交，撤销订单
                            if not order_filled:
                                api.cancel_order(order_id)
                                console.print(
                                    f"{time.strftime('%X')} SHFE{symbol}昨空仓平仓订单0.3秒未成交，已撤销",
                                    style="warning"
                                )
                                logging.info(f"SHFE{symbol}昨空仓平仓订单0.3秒未成交，已撤销: {order_id}")
                    else:
                        limit_price = quote.ask_price1 + 2 * quote.price_tick
                        if position.pos_short > 0:
                            # 平仓并获取订单ID
                            order_id = api.insert_order(
                                symbol=symbol,
                                direction="BUY",
                                offset="CLOSE",
                                volume=position.pos_short,
                                limit_price=limit_price
                            )
                            console.print(
                                f"{time.strftime('%X')} 平{symbol}空仓(均线追踪止损): 手数: {position.pos_short}, 订单ID: {order_id}",
                                style="trade"
                            )
                            logging.info(
                                f"平{symbol}空仓(均线追踪止损): 手数: {position.pos_short}, 平仓价格: {limit_price}, 订单ID: {order_id}"
                            )

                            # 检查订单是否在0.3秒内成交
                            deadline = time.time() + 0.3
                            order_filled = False
                            while time.time() < deadline:
                                api.wait_update(deadline=deadline)
                                order = api.get_order(order_id)
                                if order and order['status'] == 'FINISHED':
                                    order_filled = True
                                    console.print(
                                        f"{time.strftime('%X')} {symbol}空仓平仓订单已成交",
                                        style="success"
                                    )
                                    logging.info(f"{symbol}空仓平仓订单已成交: {order_id}")
                                    insert_trade_record(trade_time, symbol, "BUY", "CLOSE", position.pos_short, limit_price, "均线追踪止损")
                                    break

                            # 如果未成交，撤销订单
                            if not order_filled:
                                api.cancel_order(order_id)
                                console.print(
                                    f"{time.strftime('%X')} {symbol}空仓平仓订单0.3秒未成交，已撤销",
                                    style="warning"
                                )
                                logging.info(f"{symbol}空仓平仓订单0.3秒未成交，已撤销: {order_id}")


                # 处理多单
                if trading_line[-2] < short_line[-2]:
                    if symbol.startswith('SHFE'):
                        if position.pos_long_today > 0:
                            limit_price = quote.bid_price1 - 2 * quote.price_tick
                            # 平仓并获取订单ID
                            order_id = api.insert_order(
                                symbol=symbol,
                                direction="SELL",
                                offset="CLOSETODAY",
                                volume=position.pos_long_today,
                                limit_price=limit_price
                            )
                            console.print(
                                f"{time.strftime('%X')} 平SHFE{symbol}今多仓(均线追踪止损): 手数: {position.pos_long_today}, 订单ID: {order_id}",
                                style="trade"
                            )
                            logging.info(
                                f"平SHFE{symbol}今多仓(均线追踪止损): 手数: {position.pos_long_today}, 平仓价格: {limit_price}, 订单ID: {order_id}"
                            )

                            # 检查订单是否在0.3秒内成交
                            deadline = time.time() + 0.3
                            order_filled = False
                            while time.time() < deadline:
                                api.wait_update(deadline=deadline)
                                order = api.get_order(order_id)
                                if order and order['status'] == 'FINISHED':
                                    order_filled = True
                                    console.print(
                                        f"{time.strftime('%X')} SHFE{symbol}今多仓平仓订单已成交",
                                        style="success"
                                    )
                                    logging.info(f"SHFE{symbol}今多仓平仓订单已成交: {order_id}")
                                    insert_trade_record(trade_time, symbol, "SELL", "CLOSETODAY", position.pos_long_today, limit_price, "均线追踪止损")
                                    break

                            # 如果未成交，撤销订单
                            if not order_filled:
                                api.cancel_order(order_id)
                                console.print(
                                    f"{time.strftime('%X')} SHFE{symbol}今多仓平仓订单0.3秒未成交，已撤销",
                                    style="warning"
                                )
                                logging.info(f"SHFE{symbol}今多仓平仓订单0.3秒未成交，已撤销: {order_id}")
                        if position.pos_long_his > 0:
                            limit_price = quote.bid_price1 - 2 * quote.price_tick
                            volume = position.pos_long_his
                            if volume > 0:
                                # 平仓并获取订单ID
                                order_id = api.insert_order(
                                    symbol=symbol,
                                    direction="SELL",
                                    offset="CLOSE",
                                    volume=volume,
                                    limit_price=limit_price
                                )
                                console.print(
                                    f"{time.strftime('%X')} 平SHFE{symbol}昨多仓(均线追踪止损): 手数: {volume}, 订单ID: {order_id}",
                                    style="trade"
                                )
                                # 仅保留下单信息日志
                                logging.info(
                                    f"平SHFE{symbol}昨多仓(均线追踪止损): 手数: {volume}, 平仓价格: {limit_price}, 订单ID: {order_id}"
                                )

                                # 检查订单是否在0.3秒内成交
                                deadline = time.time() + 0.3
                                order_filled = False
                                while time.time() < deadline:
                                    api.wait_update(deadline=deadline)
                                    order = api.get_order(order_id)
                                    if order and order['status'] == 'FINISHED':
                                        order_filled = True
                                        console.print(
                                            f"{time.strftime('%X')} SHFE{symbol}昨多仓平仓订单已成交",
                                            style="success"
                                        )
                                        logging.info(f"SHFE{symbol}昨多仓平仓订单已成交: {order_id}")
                                        insert_trade_record(trade_time, symbol, "SELL", "CLOSE", volume, limit_price, "均线追踪止损")
                                        break

                                # 如果未成交，撤销订单
                                if not order_filled:
                                    api.cancel_order(order_id)
                                    console.print(
                                        f"{time.strftime('%X')} SHFE{symbol}昨多仓平仓订单0.3秒未成交，已撤销",
                                        style="warning"
                                    )
                                    logging.info(f"SHFE{symbol}昨多仓平仓订单0.3秒未成交，已撤销: {order_id}")
                    else:
                        if position.pos_long>0:
                            limit_price = quote.bid_price1 - 2 * quote.price_tick
                            # 平仓并获取订单ID
                            order_id = api.insert_order(
                                symbol=symbol,
                                direction="SELL",
                                offset="CLOSE",
                                volume=position.pos_long,
                                limit_price=limit_price
                            )
                            console.print(
                                f"{time.strftime('%X')} 平{symbol}多仓(均线追踪止损): 手数: {position.pos_long}, 订单ID: {order_id}",
                                style="trade"
                            )
                            logging.info(
                                f"平{symbol}多仓(均线追踪止损): 手数: {position.pos_long}, 平仓价格: {limit_price}, 订单ID: {order_id}"
                            )

                            # 检查订单是否在0.3秒内成交
                            deadline = time.time() + 0.3
                            order_filled = False
                            while time.time() < deadline:
                                api.wait_update(deadline=deadline)
                                order = api.get_order(order_id)
                                if order and order['status'] == 'FINISHED':
                                    order_filled = True
                                    console.print(
                                        f"{time.strftime('%X')} {symbol}多仓平仓订单已成交",
                                        style="success"
                                    )
                                    logging.info(f"{symbol}多仓平仓订单已成交: {order_id}")
                                    insert_trade_record(trade_time, symbol, "SELL", "CLOSE", position.pos_long, limit_price, "均线追踪止损")
                                    break

                                # 如果未成交，撤销订单
                                if not order_filled:
                                    api.cancel_order(order_id)
                                    console.print(
                                        f"{time.strftime('%X')} {symbol}多仓平仓订单0.3秒未成交，已撤销",
                                        style="warning"
                                    )
                                    logging.info(f"{symbol}多仓平仓订单0.3秒未成交，已撤销: {order_id}")


                #****************************************开仓**************************************************
                # 获取所有配置项
                configs = get_all_configs()
                open_auto = configs.get('open_auto', 'off').lower() == 'on'
                if  open_auto:
                    # 首先检查并撤销该品种的所有未成交订单
                    try:
                        # 获取当前所有未成交订单
                        orders = api.get_order()
                        # 处理不同类型的返回值
                        order_list = []
                        try:
                            # 检查是否为tqsdk.entity.Entity类型
                            if hasattr(orders, 'list') and callable(orders.list):
                                # 使用Entity的list方法获取订单列表
                                order_list = orders.list()
                            elif isinstance(orders, list):
                                order_list = orders
                            else:
                                # 尝试直接转换为列表
                                order_list = list(orders)
                        except Exception as e:
                            console.print(f"{time.strftime('%X')} 转换订单数据类型时出错: {str(e)}", style="warning")
                            logging.warning(f"转换订单数据类型时出错: {str(e)}")

                        # 处理订单列表
                        for order in order_list:
                            # 确保order是字典或具有get方法的对象
                            if hasattr(order, 'get') or isinstance(order, dict):
                                # 统一使用get方法访问属性
                                order_symbol = order.get('symbol') if hasattr(order, 'get') else order['symbol']
                                order_status = order.get('status') if hasattr(order, 'get') else order['status']
                                order_id = order.get('order_id') if hasattr(order, 'get') else order['order_id']

                                if order_symbol == symbol and order_status != 'FINISHED' and order_status != 'CANCELLED':
                                    if order_id:
                                        console.print(
                                            f"{time.strftime('%X')} 发现{symbol}未成交订单{order_id}，尝试撤销",
                                            style="warning"
                                        )
                                        logging.info(f"发现{symbol}未成交订单{order_id}，尝试撤销")
                                        api.cancel_order(order_id)
                                        # 等待撤销完成
                                        cancel_deadline = time.time() + 0.5
                                        while time.time() < cancel_deadline:
                                            api.wait_update(deadline=cancel_deadline)
                                            updated_order = api.get_order(order_id)
                                            if updated_order:
                                                # 确保updated_order是字典或具有get方法的对象
                                                if hasattr(updated_order, 'get') or isinstance(updated_order, dict):
                                                    updated_status = updated_order.get('status') if hasattr(updated_order, 'get') else updated_order['status']
                                                    if updated_status == 'CANCELLED':
                                                        console.print(
                                                            f"{time.strftime('%X')} {symbol}未成交订单{order_id}已撤销",
                                                            style="success"
                                                        )
                                                        logging.info(f"{symbol}未成交订单{order_id}已撤销")
                                                        break
                                                else:
                                                    console.print(f"{time.strftime('%X')} 更新后的订单数据类型异常: {type(updated_order)}", style="warning")
                                                    logging.warning(f"更新后的订单数据类型异常，不是字典或没有get方法: {updated_order}")
                                            else:
                                                console.print(f"{time.strftime('%X')} 未找到订单{order_id}的更新信息", style="warning")
                                                logging.warning(f"未找到订单{order_id}的更新信息")
                                    else:
                                        console.print(f"{time.strftime('%X')} 发现{symbol}未成交订单但缺少order_id", style="warning")
                                        logging.warning(f"发现{symbol}未成交订单但缺少order_id: {order}")
                                else:
                                    console.print(f"{time.strftime('%X')} 订单数据类型异常: {type(order)}", style="warning")
                                    logging.warning(f"订单数据类型异常，不是字典: {order}")
                        # 移除错误的else分支，for循环正常结束表示已成功处理所有订单
                    except Exception as e:
                        console.print(f"检查和撤销{symbol}未成交订单时出错: {str(e)}", style="error")
                        logging.error(f"检查和撤销{symbol}未成交订单时出错: {str(e)}", exc_info=True)
                    # 检查是否需要开多仓
                    can_open, reason = check_position_and_orders(api, symbol)
                    if can_open and position.pos_long==0 and (dks == "只做多" or dks == "双向") and trading_line[-2] > short_line[-2] and trading_line[-3] < short_line[-3] and symbol not in opened_positions:
                        # 使用锁保护opened_positions的访问
                        with position_lock:
                            # 对上海交易所的商品开多仓
                            if symbol.startswith('SHFE'):
                                limit_price = quote.ask_price1 + 2 * quote.price_tick
                                # 开仓并获取订单ID
                                order_id = api.insert_order(
                                    symbol=symbol,
                                    direction="BUY",
                                    offset="OPEN",
                                    volume=1,  # 开仓手数，可根据需求调整
                                    limit_price=limit_price
                                )
                                console.print(
                                    f"{time.strftime('%X')} 开SHFE{symbol}多仓: 手数: 1, 订单ID: {order_id}",
                                    style="trade"
                                )
                                logging.info(
                                    f"开SHFE{symbol}多仓: 手数: 1, 开仓价格: {limit_price}, 订单ID: {order_id}"
                                )

                                # 检查订单是否在0.3秒内成交
                                deadline = time.time() + 0.3
                                order_filled = False
                                while time.time() < deadline:
                                    api.wait_update(deadline=deadline)
                                    order = api.get_order(order_id)
                                    if order and order['status'] == 'FINISHED':
                                        order_filled = True
                                        console.print(
                                            f"{time.strftime('%X')} SHFE{symbol}多仓订单已成交",
                                            style="success"
                                        )
                                        logging.info(f"SHFE{symbol}多仓订单已成交: {order_id}")
                                        insert_trade_record(trade_time, symbol, "BUY", "OPEN", 1, limit_price, "开多仓")
                                        with position_lock:
                                            opened_positions.add(symbol)  # 记录已开多仓
                                            logging.info(f"已将{symbol}添加到opened_positions集合，当前集合大小: {len(opened_positions)}")
                                        break

                                # 如果未成交，撤销订单并从opened_positions中移除
                                if not order_filled:
                                    api.cancel_order(order_id)
                                    console.print(
                                        f"{time.strftime('%X')} SHFE{symbol}多仓订单0.3秒未成交，已撤销",
                                        style="warning"
                                    )
                                    logging.info(f"SHFE{symbol}多仓订单0.3秒未成交，已撤销: {order_id}")
                                    # 确保该品种可以在下一个循环中再次尝试开仓
                                    with position_lock:
                                        if symbol in opened_positions:
                                            opened_positions.remove(symbol)
                                            logging.info(f"已将{symbol}从opened_positions集合中移除，当前集合大小: {len(opened_positions)}")
                            # 非上海交易所的商品开多仓
                            else:
                                limit_price = quote.ask_price1 + 2 * quote.price_tick
                                # 开仓并获取订单ID
                                order_id = api.insert_order(
                                    symbol=symbol,
                                    direction="BUY",
                                    offset="OPEN",
                                    volume=1,  # 开仓手数，可根据需求调整
                                    limit_price=limit_price
                                )
                                console.print(
                                    f"{time.strftime('%X')} 开{symbol}多仓: 手数: 1, 订单ID: {order_id}",
                                    style="trade"
                                )
                                logging.info(
                                    f"开{symbol}多仓: 手数: 1, 开仓价格: {limit_price}, 订单ID: {order_id}"
                                )

                                # 检查订单是否在0.3秒内成交
                                deadline = time.time() + 0.3
                                order_filled = False
                                while time.time() < deadline:
                                    api.wait_update(deadline=deadline)
                                    order = api.get_order(order_id)
                                    if order and order['status'] == 'FINISHED':
                                        order_filled = True
                                        console.print(
                                            f"{time.strftime('%X')} {symbol}多仓订单已成交",
                                            style="success"
                                        )
                                        logging.info(f"{symbol}多仓订单已成交: {order_id}")
                                        insert_trade_record(trade_time, symbol, "BUY", "OPEN", 1, limit_price, "开多仓")
                                        with position_lock:
                                            opened_positions.add(symbol)  # 记录已开多仓
                                            logging.info(f"已将{symbol}添加到opened_positions集合，当前集合大小: {len(opened_positions)}")
                                        break

                            # 如果未成交，撤销订单并从opened_positions中移除
                            if not order_filled:
                                api.cancel_order(order_id)
                                console.print(
                                    f"{time.strftime('%X')} {symbol}多仓订单0.3秒未成交，已撤销",
                                    style="warning"
                                )
                                logging.info(f"{symbol}多仓订单0.3秒未成交，已撤销: {order_id}")
                                # 确保该品种可以在下一个循环中再次尝试开仓
                                with position_lock:
                                    if symbol in opened_positions:
                                        opened_positions.remove(symbol)
                                        logging.info(f"已将{symbol}从opened_positions集合中移除，当前集合大小: {len(opened_positions)}")
                    # 检查是否需要开空仓
                    can_open, reason = check_position_and_orders(api, symbol)
                    if can_open and position.pos_short==0 and (dks == "只做空" or dks == "双向") and trading_line[-2] < short_line[-2] and trading_line[-3] > short_line[-3] and symbol not in opened_positions:
                        # 使用锁保护opened_positions的访问
                        with position_lock:
                        # 对上海交易所的商品开空仓
                            if symbol.startswith('SHFE'):
                                limit_price = quote.bid_price1 - 2 * quote.price_tick
                                # 开仓并获取订单ID
                                order_id = api.insert_order(
                                    symbol=symbol,
                                    direction="SELL",
                                    offset="OPEN",
                                    volume=1,  # 开仓手数，可根据需求调整
                                    limit_price=limit_price
                                )
                                console.print(
                                f"{time.strftime('%X')} 开SHFE{symbol}空仓: 手数: 1, 订单ID: {order_id}",
                                style="trade"
                            )
                            logging.info(
                                f"开SHFE{symbol}空仓: 手数: 1, 开仓价格: {limit_price}, 订单ID: {order_id}"
                            )

                            # 检查订单是否在0.3秒内成交
                            deadline = time.time() + 0.3
                            order_filled = False
                            while time.time() < deadline:
                                api.wait_update(deadline=deadline)
                                order = api.get_order(order_id)
                                if order and order['status'] == 'FINISHED':
                                    order_filled = True
                                    console.print(
                                        f"{time.strftime('%X')} SHFE{symbol}空仓订单已成交",
                                        style="success"
                                    )
                                    logging.info(f"SHFE{symbol}空仓订单已成交: {order_id}")
                                    insert_trade_record(trade_time, symbol, "SELL", "OPEN", 1, limit_price, "开空仓")
                                    opened_positions.add(symbol)  # 记录已开空仓
                                    logging.info(f"已将{symbol}添加到opened_positions集合，当前集合大小: {len(opened_positions)}")
                                    break

                                # 如果未成交，撤销订单并从opened_positions中移除
                                if not order_filled:
                                    api.cancel_order(order_id)
                                    console.print(
                                        f"{time.strftime('%X')} SHFE{symbol}空仓订单0.3秒未成交，已撤销",
                                        style="warning"
                                    )
                                    logging.info(f"SHFE{symbol}空仓订单0.3秒未成交，已撤销: {order_id}")
                                    # 确保该品种可以在下一个循环中再次尝试开仓
                                    with position_lock:
                                        if symbol in opened_positions:
                                            opened_positions.remove(symbol)
                                            logging.info(f"已将{symbol}从opened_positions集合中移除，当前集合大小: {len(opened_positions)}")
                            # 非上海交易所的商品开空仓
                            else:
                                limit_price = quote.bid_price1 - 2 * quote.price_tick
                                # 开仓并获取订单ID
                                order_id = api.insert_order(
                                    symbol=symbol,
                                    direction="SELL",
                                    offset="OPEN",
                                    volume=1,  # 开仓手数，可根据需求调整
                                    limit_price=limit_price
                                )
                                console.print(
                                    f"{time.strftime('%X')} 开{symbol}空仓: 手数: 1, 订单ID: {order_id}",
                                    style="trade"
                                )
                                logging.info(
                                    f"开{symbol}空仓: 手数: 1, 开仓价格: {limit_price}, 订单ID: {order_id}"
                                )

                                # 检查订单是否在0.3秒内成交
                                deadline = time.time() + 0.3
                                order_filled = False
                                while time.time() < deadline:
                                    api.wait_update(deadline=deadline)
                                    order = api.get_order(order_id)
                                    if order and order['status'] == 'FINISHED':
                                        order_filled = True
                                        console.print(
                                            f"{time.strftime('%X')} {symbol}空仓订单已成交",
                                            style="success"
                                        )
                                        logging.info(f"{symbol}空仓订单已成交: {order_id}")
                                        insert_trade_record(trade_time, symbol, "SELL", "OPEN", 1, limit_price, "开空仓")
                                        with position_lock:
                                            opened_positions.add(symbol)  # 记录已开空仓
                                            logging.info(f"已将{symbol}添加到opened_positions集合，当前集合大小: {len(opened_positions)}")
                                        break

                                # 如果未成交，撤销订单并从opened_positions中移除
                                if not order_filled:
                                    api.cancel_order(order_id)
                                    console.print(
                                        f"{time.strftime('%X')} {symbol}空仓订单0.3秒未成交，已撤销",
                                        style="warning"
                                    )
                                    logging.info(f"{symbol}空仓订单0.3秒未成交，已撤销: {order_id}")
                                    # 确保该品种可以在下一个循环中再次尝试开仓
                                    with position_lock:
                                        if symbol in opened_positions:
                                            opened_positions.remove(symbol)
                                            logging.info(f"已将{symbol}从opened_positions集合中移除，当前集合大小: {len(opened_positions)}")
                else:
                    console.print(f"{time.strftime('%X')} 自动开仓功能已关闭，跳过开仓检查", style="warning")

        except Exception as e:
            console.print(f"处理 {symbol} 止损逻辑时出错: {e}", style="error")


        except Exception as e:
            console.print(f"处理 {symbol} 止损逻辑时出错: {e}", style="error")


if __name__ == "__main__":
    try:
        api = TqApi(account=TqKq(), auth=TqAuth("cps168", "alibaba"))
        # # 获取待监控的品种
        # symbol_mtp_list = get_symbols()
        while True:
            #获取待监控的品种，把函数放在while循环内，在GUI界面修改参数可以实时生效
            symbol_mtp_list = get_symbols()
            deadline = time.time() + 2
            api.wait_update(deadline=deadline)
            console.print(f"**********{time.strftime('%X')} **********", style="warning")
            for symbol in symbol_mtp_list:
                stop_loss(symbol)
            time.sleep(0.2)

    except KeyboardInterrupt:
        pass
    finally:
        api.close()
        console.print("程序已停止", style="info")